home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Games / NetHack 3.1.3 / source / src / cmd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-01  |  26.5 KB  |  1,162 lines  |  [TEXT/R*ch]

  1. /*    SCCS Id: @(#)cmd.c    3.1    93/06/18    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6. #include "func_tab.h"
  7.  
  8. /*
  9.  * Some systems may have getchar() return EOF for various reasons, and
  10.  * we should not quit before seeing at least NR_OF_EOFS consecutive EOFs.
  11.  */
  12. #if defined(SYSV) || defined(DGUX) || defined(HPUX)
  13. #define    NR_OF_EOFS    20
  14. #endif
  15.  
  16. #ifdef DUMB    /* stuff commented out in extern.h, but needed here */
  17. extern int NDECL(doapply); /**/
  18. extern int NDECL(dorub); /**/
  19. extern int NDECL(dojump); /**/
  20. extern int NDECL(doextlist); /**/
  21. extern int NDECL(dodrop); /**/
  22. extern int NDECL(doddrop); /**/
  23. extern int NDECL(dodown); /**/
  24. extern int NDECL(doup); /**/
  25. extern int NDECL(donull); /**/
  26. extern int NDECL(dowipe); /**/
  27. extern int NDECL(do_mname); /**/
  28. extern int NDECL(ddocall); /**/
  29. extern int NDECL(dotakeoff); /**/
  30. extern int NDECL(doremring); /**/
  31. extern int NDECL(dowear); /**/
  32. extern int NDECL(doputon); /**/
  33. extern int NDECL(doddoremarm); /**/
  34. extern int NDECL(dokick); /**/
  35. extern int NDECL(dothrow); /**/
  36. extern int NDECL(doeat); /**/
  37. extern int NDECL(done2); /**/
  38. extern int NDECL(doengrave); /**/
  39. extern int NDECL(dopickup); /**/
  40. extern int NDECL(ddoinv); /**/
  41. extern int NDECL(dotypeinv); /**/
  42. extern int NDECL(dolook); /**/
  43. extern int NDECL(doprgold); /**/
  44. extern int NDECL(doprwep); /**/
  45. extern int NDECL(doprarm); /**/
  46. extern int NDECL(doprring); /**/
  47. extern int NDECL(dopramulet); /**/
  48. extern int NDECL(doprtool); /**/
  49. extern int NDECL(dosuspend); /**/
  50. extern int NDECL(doforce); /**/
  51. extern int NDECL(doopen); /**/
  52. extern int NDECL(doclose); /**/
  53. extern int NDECL(dosh); /**/
  54. extern int NDECL(dodiscovered); /**/
  55. extern int NDECL(doset); /**/
  56. extern int NDECL(dotogglepickup); /**/
  57. extern int NDECL(dowhatis); /**/
  58. extern int NDECL(doquickwhatis); /**/
  59. extern int NDECL(dowhatdoes); /**/
  60. extern int NDECL(dohelp); /**/
  61. extern int NDECL(dohistory); /**/
  62. extern int NDECL(doloot); /**/
  63. extern int NDECL(dodrink); /**/
  64. extern int NDECL(dodip); /**/
  65. extern int NDECL(dosacrifice); /**/
  66. extern int NDECL(dopray); /**/
  67. extern int NDECL(doturn); /**/
  68. extern int NDECL(doredraw); /**/
  69. extern int NDECL(doread); /**/
  70. extern int NDECL(dosave); /**/
  71. extern int NDECL(dosearch); /**/
  72. extern int NDECL(doidtrap); /**/
  73. extern int NDECL(dopay); /**/
  74. extern int NDECL(dosit); /**/
  75. extern int NDECL(dotalk); /**/
  76. extern int NDECL(docast); /**/
  77. extern int NDECL(dovspell); /**/
  78. extern int NDECL(dotele); /**/
  79. extern int NDECL(dountrap); /**/
  80. extern int NDECL(doversion); /**/
  81. extern int NDECL(doextversion); /**/
  82. extern int NDECL(dowield); /**/
  83. extern int NDECL(dozap); /**/
  84. extern int NDECL(doorganize); /**/
  85. #endif /* DUMB */
  86.  
  87. #ifdef OVL1
  88. static int NDECL((*timed_occ_fn));
  89. #endif /* OVL1 */
  90.  
  91. STATIC_PTR int NDECL(doprev_message);
  92. STATIC_PTR int NDECL(timed_occupation);
  93. STATIC_PTR int NDECL(doextcmd);
  94. # ifdef POLYSELF
  95. STATIC_PTR int NDECL(domonability);
  96. # endif
  97. # ifdef WIZARD
  98. STATIC_PTR int NDECL(wiz_wish);
  99. STATIC_PTR int NDECL(wiz_identify);
  100. STATIC_PTR int NDECL(wiz_map);
  101. STATIC_PTR int NDECL(wiz_genesis);
  102. STATIC_PTR int NDECL(wiz_where);
  103. STATIC_PTR int NDECL(wiz_detect);
  104. STATIC_PTR int NDECL(wiz_level_tele);
  105. # endif
  106. # ifdef EXPLORE_MODE
  107. STATIC_PTR int NDECL(enter_explore_mode);
  108. # endif
  109. # if defined(WIZARD) || defined(EXPLORE_MODE)
  110. STATIC_PTR int NDECL(wiz_attributes);
  111. # endif
  112.  
  113. #ifdef OVLB
  114. static void FDECL(enlght_line, (const char *,const char *,const char *));
  115. #ifdef UNIX
  116. static void NDECL(end_of_input);
  117. #endif
  118. #endif /* OVLB */
  119.  
  120. STATIC_OVL char *NDECL(parse);
  121.  
  122. #ifdef UNIX
  123. extern boolean hu;
  124. #endif
  125.  
  126. #ifdef OVL1
  127.  
  128. STATIC_PTR int
  129. doprev_message()
  130. {
  131.     return nh_doprev_message();
  132. }
  133.  
  134. /* Count down by decrementing multi */
  135. STATIC_PTR int
  136. timed_occupation() {
  137.     (*timed_occ_fn)();
  138.     if (multi > 0)
  139.         multi--;
  140.     return multi > 0;
  141. }
  142.  
  143. /* If you have moved since initially setting some occupations, they
  144.  * now shouldn't be able to restart.
  145.  *
  146.  * The basic rule is that if you are carrying it, you can continue
  147.  * since it is with you.  If you are acting on something at a distance,
  148.  * your orientation to it must have changed when you moved.
  149.  *
  150.  * The exception to this is taking off items, since they can be taken
  151.  * off in a number of ways in the intervening time, screwing up ordering.
  152.  *
  153.  *    Currently:    Take off all armor.
  154.  *            Picking Locks / Forcing Chests.
  155.  */
  156. void
  157. reset_occupations() {
  158.  
  159.     reset_remarm();
  160.     reset_pick();
  161. }
  162.  
  163. /* If a time is given, use it to timeout this function, otherwise the
  164.  * function times out by its own means.
  165.  */
  166. void
  167. set_occupation(fn, txt, xtime)
  168. int NDECL((*fn));
  169. const char *txt;
  170. int xtime;
  171. {
  172.     if (xtime) {
  173.         occupation = timed_occupation;
  174.         timed_occ_fn = fn;
  175.     } else
  176.         occupation = fn;
  177.     occtxt = txt;
  178.     occtime = 0;
  179.     return;
  180. }
  181.  
  182. #ifdef REDO
  183.  
  184. static char NDECL(popch);
  185.  
  186. /* Provide a means to redo the last command.  The flag `in_doagain' is set
  187.  * to true while redoing the command.  This flag is tested in commands that
  188.  * require additional input (like `throw' which requires a thing and a
  189.  * direction), and the input prompt is not shown.  Also, while in_doagain is
  190.  * TRUE, no keystrokes can be saved into the saveq.
  191.  */
  192. #define BSIZE 20
  193. static char pushq[BSIZE], saveq[BSIZE];
  194. static NEARDATA int phead, ptail, shead, stail;
  195.  
  196. static char
  197. popch() {
  198.     /* If occupied, return '\0', letting tgetch know a character should
  199.      * be read from the keyboard.  If the character read is not the
  200.      * ABORT character (as checked in pcmain.c), that character will be
  201.      * pushed back on the pushq.
  202.      */
  203.     if (occupation) return '\0';
  204.     if (in_doagain) return(char)((shead != stail) ? saveq[stail++] : '\0');
  205.     else        return(char)((phead != ptail) ? pushq[ptail++] : '\0');
  206. }
  207.  
  208. char
  209. pgetchar() {        /* curtesy of aeb@cwi.nl */
  210.     register int ch;
  211.  
  212.     if(!(ch = popch()))
  213.         ch = nhgetch();
  214.     return((char)ch);
  215. }
  216.  
  217. /* A ch == 0 resets the pushq */
  218. void
  219. pushch(ch)
  220. char ch;
  221. {
  222.     if (!ch)
  223.         phead = ptail = 0;
  224.     if (phead < BSIZE)
  225.         pushq[phead++] = ch;
  226.     return;
  227. }
  228.  
  229. /* A ch == 0 resets the saveq.    Only save keystrokes when not
  230.  * replaying a previous command.
  231.  */
  232. void
  233. savech(ch)
  234. char ch;
  235. {
  236.     if (!in_doagain) {
  237.         if (!ch)
  238.             phead = ptail = shead = stail = 0;
  239.         else if (shead < BSIZE)
  240.             saveq[shead++] = ch;
  241.     }
  242.     return;
  243. }
  244. #endif /* REDO */
  245.  
  246. #endif /* OVL1 */
  247. #ifdef OVLB
  248.  
  249. STATIC_PTR int
  250. doextcmd()    /* here after # - now read a full-word command */
  251. {
  252.     char buf[BUFSZ];
  253.     register const struct ext_func_tab *efp = extcmdlist;
  254. again:
  255. #ifdef COM_COMPL
  256.     get_ext_cmd(buf);
  257. #else
  258.     getlin("#", buf);
  259. #endif
  260.     if(buf[0] == '\0' || buf[0] == '\033')
  261.         return 0;
  262.     if(buf[0] == '?') {
  263.         (void) doextlist();
  264.         goto again;
  265.     }
  266.     while(efp->ef_txt) {
  267.         if(!strncmpi(efp->ef_txt, buf,BUFSIZ))
  268.             return (*(efp->ef_funct))();
  269.         efp++;
  270.     }
  271.     pline("%s: unknown extended command.", buf);
  272.     return 0;
  273. }
  274.  
  275. int
  276. doextlist()    /* here after #? - now list all full-word commands */
  277. {
  278.     register const struct ext_func_tab *efp;
  279.     char     buf[BUFSZ];
  280.     winid datawin;
  281.  
  282.     datawin = create_nhwindow(NHW_TEXT);
  283.     putstr(datawin, 0, "");
  284.     putstr(datawin, 0, "            Extended Commands List");
  285.     putstr(datawin, 0, "");
  286. #ifdef COM_COMPL
  287.     putstr(datawin, 0, "    Press '#', then type (first letter only):");
  288. #else
  289.     putstr(datawin, 0, "    Press '#', then type:");
  290. #endif
  291.     putstr(datawin, 0, "");
  292.  
  293.     for(efp = extcmdlist; efp->ef_txt; efp++) {
  294.         Sprintf(buf, "    %-8s  - %s.", efp->ef_txt, efp->ef_desc);
  295.         putstr(datawin, 0, buf);
  296.     }
  297.     display_nhwindow(datawin, FALSE);
  298.     destroy_nhwindow(datawin);
  299.     return 0;
  300. }
  301.  
  302. #ifdef POLYSELF
  303. STATIC_PTR int
  304. domonability()
  305. {
  306.     if (can_breathe(uasmon)) return dobreathe();
  307.     else if (attacktype(uasmon, AT_SPIT)) return dospit();
  308.     else if (u.usym == S_NYMPH) return doremove();
  309.     else if (u.usym == S_UMBER) return doconfuse();
  310.     else if (is_were(uasmon)) return dosummon();
  311.     else if (webmaker(uasmon)) return dospinweb();
  312.     else if (is_hider(uasmon)) return dohide();
  313.     else if(u.umonnum == PM_GREMLIN) {
  314.         if(IS_FOUNTAIN(levl[u.ux][u.uy].typ)) {
  315.         struct monst *mtmp;
  316.         if ((mtmp = cloneu()) != 0) {
  317.             mtmp->mhpmax = (u.mhmax /= 2);
  318.             You("multiply.");
  319.             dryup(u.ux,u.uy);
  320.         }
  321.         } else pline("There is no fountain here.");
  322.     }
  323.     else if (u.usym == S_UNICORN) {
  324.         use_unicorn_horn((struct obj *)0);
  325.         return 1;
  326.     } else if (u.umonnum == PM_MIND_FLAYER) return domindblast();
  327.     else if (uasmon->msound == MS_SHRIEK) {
  328.         You("shriek.");
  329.         aggravate();
  330.     } else if (u.umonnum >= 0)
  331.         pline("Any special ability you may have is purely reflexive.");
  332.     else You("don't have a special ability!");
  333.     return 0;
  334. }
  335. #endif
  336.  
  337. #ifdef EXPLORE_MODE
  338. STATIC_PTR int
  339. enter_explore_mode()
  340. {
  341.     if(!discover && !wizard) {
  342.         pline("Beware!  From explore mode there will be no return to normal game.");
  343.         if (yn("Do you want to enter explore mode?") == 'y') {
  344.             clear_nhwindow(WIN_MESSAGE);
  345.             You("are now in non-scoring explore mode.");
  346.             discover = TRUE;
  347.         }
  348.         else {
  349.             clear_nhwindow(WIN_MESSAGE);
  350.             pline("Resuming normal game.");
  351.         }
  352.     }
  353.     return 0;
  354. }
  355. #endif
  356.  
  357. #ifdef WIZARD
  358. STATIC_PTR int
  359. wiz_wish()    /* Unlimited wishes for debug mode by Paul Polderman */
  360. {
  361.     if (wizard) {
  362.         makewish();
  363.         (void) encumber_msg();
  364.     } else
  365.         pline("Unavailable command '^W'.");
  366.     return 0;
  367. }
  368.  
  369. STATIC_PTR int
  370. wiz_identify()
  371. {
  372.     struct obj *obj;
  373.  
  374.     if (!wizard)
  375.         pline("Unavailable command '^I'.");
  376.     else {
  377.         for (obj = invent; obj; obj = obj->nobj)
  378.             if (!objects[obj->otyp].oc_name_known || !obj->known
  379.                 || !obj->dknown || !obj->bknown || !obj->rknown)
  380.                 (void) identify(obj);
  381.     }
  382.     return 0;
  383. }
  384.  
  385. STATIC_PTR int
  386. wiz_map()
  387. {
  388.     if (wizard)    do_mapping();
  389.     else        pline("Unavailable command '^F'.");
  390.     return 0;
  391. }
  392.  
  393. STATIC_PTR int
  394. wiz_genesis()
  395. {
  396.     if (wizard)    (void) create_particular();
  397.     else        pline("Unavailable command '^G'.");
  398.     return 0;
  399. }
  400.  
  401. STATIC_PTR int
  402. wiz_where()
  403. {
  404.     if (wizard) print_dungeon();
  405.     else        pline("Unavailable command '^O'.");
  406.     return 0;
  407. }
  408.  
  409. STATIC_PTR int
  410. wiz_detect()
  411. {
  412.     if(wizard)  (void) findit();
  413.     else        pline("Unavailable command '^E'.");
  414.     return 0;
  415. }
  416.  
  417. STATIC_PTR int
  418. wiz_level_tele()
  419. {
  420.     if (wizard)    level_tele();
  421.     else        pline("Unavailable command '^V'.");
  422.     return 0;
  423. }
  424.  
  425. #endif /* WIZARD */
  426.  
  427. /* -enlightenment- */
  428. static winid en_win;
  429. static const char
  430.     *You_ = "You ",
  431.     *are  = "are ",  *were  = "were ",
  432.     *have = "have ", *had   = "had ",
  433.     *can  = "can ",  *could = "could ";
  434.  
  435. #define enl_msg(prefix,present,past,suffix) \
  436.             enlght_line(prefix, final ? past : present, suffix)
  437. #define you_are(attr)    enl_msg(You_,are,were,attr)
  438. #define you_have(attr)    enl_msg(You_,have,had,attr)
  439. #define you_can(attr)    enl_msg(You_,can,could,attr)
  440.  
  441. static void
  442. enlght_line(start, middle, end)
  443. const char *start, *middle, *end;
  444. {
  445.     char buf[BUFSZ];
  446.  
  447.     Sprintf(buf, "%s%s%s.", start, middle, end);
  448.     putstr(en_win, 0, buf);
  449. }
  450.  
  451. void
  452. enlightenment(final)
  453. boolean final;
  454. {
  455.     int ltmp;
  456.     char buf[BUFSZ];
  457.  
  458.     en_win = create_nhwindow(NHW_MENU);
  459.     putstr(en_win, 0, final ? "Final Attributes:" : "Current Attributes:");
  460.     putstr(en_win, 0, "");
  461.  
  462. #ifdef ELBERETH
  463.     if (u.uevent.uhand_of_elbereth) {
  464.         static const char *hofe_titles[3] = {
  465.                 "the Hand of Elbereth",
  466.                 "the Envoy of Balance",
  467.                 "the Glory of Arioch"
  468.         };
  469.         you_are(hofe_titles[u.uevent.uhand_of_elbereth - 1]);
  470.     }
  471. #endif
  472.  
  473.     /* note: piousness 20 matches MIN_QUEST_ALIGN (quest.h) */
  474.     if (u.ualign.record >= 20)    you_are("piously aligned");
  475.     else if (u.ualign.record > 13)    you_are("devoutly aligned");
  476.     else if (u.ualign.record > 8)    you_are("fervently aligned");
  477.     else if (u.ualign.record > 3)    you_are("stridently aligned");
  478.     else if (u.ualign.record == 3)    you_are("aligned");
  479.     else if (u.ualign.record > 0)    you_are("haltingly aligned");
  480.     else if (u.ualign.record == 0)    you_are("nominally aligned");
  481.     else if (u.ualign.record >= -3)    you_have("strayed");
  482.     else if (u.ualign.record >= -8)    you_have("sinned");
  483.     else you_have("transgressed");
  484. #ifdef WIZARD
  485.     if (wizard) {
  486.         Sprintf(buf, " %d", u.ualign.record);
  487.         enl_msg("Your alignment ", "is", "was", buf);
  488.     }
  489. #endif
  490.  
  491.     if (Telepat) you_are("telepathic");
  492.     if (Searching) you_have("automatic searching");
  493.     if (Teleportation) you_can("teleport");
  494.     if (Teleport_control) you_have("teleport control");
  495.     if (See_invisible) enl_msg(You_, "see", "saw", " invisible");
  496.     if (Invisible) you_are("invisible");
  497.     else if (Invis) you_are("invisible to others");
  498.     if (Fast) you_are((Fast & ~INTRINSIC) ? "very fast" : "fast");
  499.     if (Stealth) you_are("stealthy");
  500.     if (Regeneration) enl_msg("You regenerate", "", "d", "");
  501.     if (Hunger) enl_msg("You hunger", "", "ed", " rapidly");
  502.     if (Conflict) enl_msg("You cause", "", "d", " conflict");
  503.     if (Aggravate_monster) enl_msg("You aggravate", "", "d", " monsters");
  504.     if (Poison_resistance) you_are("poison resistant");
  505.     if (Fire_resistance) you_are("fire resistant");
  506.     if (Cold_resistance) you_are("cold resistant");
  507.     if (Shock_resistance) you_are("shock resistant");
  508.     if (Sleep_resistance) you_are("sleep resistant");
  509.     if (Disint_resistance) you_are("disintegration-resistant");
  510.     if (Protection_from_shape_changers)
  511.         you_are("protected from shape changers");
  512. #ifdef POLYSELF
  513.     if (Polymorph) you_are("polymorphing");
  514.     if (Polymorph_control) you_have("polymorph control");
  515. #endif
  516.     if (HHalluc_resistance)
  517.         enl_msg("You resist", "", "ed", " hallucinations");
  518.     if (final) {
  519.         if (Hallucination) you_are("hallucinating");
  520.         if (Stunned) you_are("stunned");
  521.         if (Confusion) you_are("confused");
  522.         if (Sick) you_are("sick");
  523.         if (Blinded) you_are("blinded");
  524.     }
  525.     if (Wounded_legs) {
  526.         Sprintf(buf, "wounded %s", makeplural(body_part(LEG)));
  527.         you_have(buf);
  528.     }
  529.     if (Glib) {
  530.         Sprintf(buf, "slippery %s", makeplural(body_part(FINGER)));
  531.         you_have(buf);
  532.     }
  533.     if (Strangled) you_are("being strangled");
  534.     if (Stoned) you_are("turning to stone");
  535.     if (Lifesaved)
  536.         enl_msg("Your life ", "will be", "would have been", " saved");
  537.     if (Adornment) you_are("adorned");
  538.     if (Warning) you_are("warned");
  539.     if (Protection) you_are("protected");
  540.     if (Reflecting) you_have("reflection");
  541.     if (Levitation) you_are("levitating");
  542. #ifdef POLYSELF
  543.     else if (is_flyer(uasmon)) you_can("fly");
  544. #endif
  545.     if (Fumbling) enl_msg("You fumble", "", "d", "");
  546.     if (Jumping) you_can("jump");
  547.     if (Wwalking) you_can("walk on water");
  548. #ifdef POLYSELF
  549.     if (passes_walls(uasmon)) you_can("walk through walls");
  550. #endif
  551.     if (Breathless) you_can("survive without air");
  552.     else if (Amphibious) you_can("breathe water");
  553.     if (Antimagic) you_are("magic-protected");
  554.     if (Displaced) you_are("displaced");
  555.     if (Clairvoyant) you_are("clairvoyant");
  556. #ifdef POLYSELF
  557.     if (u.ulycn != -1) {    
  558.         Strcpy(buf, an(mons[u.ulycn].mname));
  559.         you_are(buf);
  560.     }
  561. #endif
  562.     if (Luck) {
  563.         ltmp = abs((int)Luck);
  564.         Sprintf(buf, "%s%slucky",
  565.             ltmp >= 10 ? "extremely " : ltmp >= 5 ? "very " : "",
  566.             Luck < 0 ? "un" : "");
  567. #ifdef WIZARD
  568.         if (wizard) Sprintf(eos(buf), " (%d)", Luck);
  569. #endif
  570.         you_are(buf);
  571.     }
  572. #ifdef WIZARD
  573.      else if (wizard) enl_msg("Your luck ", "is", "was", " zero");
  574. #endif
  575.     ltmp = stone_luck(TRUE);
  576.     if (ltmp > 0) you_have("extra luck");
  577.     else if (ltmp < 0) you_have("reduced luck");
  578.     if (carrying(LUCKSTONE)) {
  579.         ltmp = stone_luck(FALSE);
  580.         if (ltmp <= 0)
  581.         enl_msg("Bad luck ", "does", "did", " not time out for you");
  582.         if (ltmp >= 0)
  583.         enl_msg("Good luck ", "does", "did", " not time out for you");
  584.     }
  585.  
  586.     if (u.umortality) {
  587.         if (u.umortality == 1)
  588.         Sprintf(buf, "once");
  589.         else
  590.         Sprintf(buf, "%d times", u.umortality);
  591.         enl_msg("You ", "have been killed ", "died ", buf);
  592.     }
  593.  
  594.     display_nhwindow(en_win, TRUE);
  595.     destroy_nhwindow(en_win);
  596.     return;
  597. }
  598.  
  599. #if defined(WIZARD) || defined(EXPLORE_MODE)
  600. STATIC_PTR int
  601. wiz_attributes()
  602. {
  603.     if (wizard || discover)
  604.         enlightenment(FALSE);
  605.     else
  606.         pline("Unavailable command '^X'.");
  607.     return 0;
  608. }
  609. #endif /* WIZARD || EXPLORE_MODE */
  610.  
  611. #endif /* OVLB */
  612. #ifdef OVL1
  613.  
  614. #ifndef M
  615. # ifndef NHSTDC
  616. #  define M(c)        (0x80 | (c))
  617. # else
  618. #  define M(c)        ((c) - 128)
  619. # endif /* NHSTDC */
  620. #endif
  621. #ifndef C
  622. #define C(c)        (0x1f & (c))
  623. #endif
  624.  
  625. static const struct func_tab cmdlist[] = {
  626.     {C('d'), dokick},    /* "D" is for door!...? */
  627. #ifdef WIZARD
  628.     {C('e'), wiz_detect},
  629.     {C('f'), wiz_map},
  630.     {C('g'), wiz_genesis},
  631.     {C('i'), wiz_identify},
  632. #endif
  633.     {C('l'), doredraw}, /* if number_pad is set */
  634. #ifdef WIZARD
  635.     {C('o'), wiz_where},
  636. #endif
  637.     {C('p'), doprev_message},
  638.     {C('r'), doredraw},
  639.     {C('t'), dotele},
  640. #ifdef WIZARD
  641.     {C('v'), wiz_level_tele},
  642.     {C('w'), wiz_wish},
  643. #endif
  644. #if defined(WIZARD) || defined(EXPLORE_MODE)
  645.     {C('x'), wiz_attributes},
  646. #endif
  647. #ifdef SUSPEND
  648.     {C('z'), dosuspend},
  649. #endif
  650.     {'a', doapply},
  651.     {'A', doddoremarm},
  652.     {M('a'), doorganize},
  653. /*    'b', 'B' : go sw */
  654.     {'c', doclose},
  655.     {'C', do_mname},
  656.     {M('c'), dotalk},
  657.     {'d', dodrop},
  658.     {'D', doddrop},
  659.     {M('d'), dodip},
  660.     {'e', doeat},
  661.     {'E', doengrave},
  662. /* Soon to be
  663.     {'f', dofight, "fighting"},
  664.     {'F', doFight, "fighting"},
  665.  */
  666.     {M('f'), doforce},
  667. /*    'g', 'G' : multiple go */
  668. /*    'h', 'H' : go west */
  669.     {'h', dohelp}, /* if number_pad is set */
  670.     {'i', ddoinv},
  671.     {'I', dotypeinv},        /* Robert Viduya */
  672.     {M('i'), doinvoke},
  673. /*    'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N' : move commands */
  674.     {'j', dojump}, /* if number_pad is on */
  675.     {M('j'), dojump},
  676.     {'k', dokick}, /* if number_pad is on */
  677.     {'l', doloot}, /* if number_pad is on */
  678.     {M('l'), doloot},
  679. /*    'n' prefixes a count if number_pad is on */
  680. #ifdef POLYSELF
  681.     {M('m'), domonability},
  682. #endif /* POLYSELF */
  683.     {'N', ddocall}, /* if number_pad is on */
  684.     {M('n'), ddocall},
  685.     {M('N'), ddocall},
  686.     {'o', doopen},
  687.     {'O', doset},
  688.     {M('o'), dosacrifice},
  689.     {'p', dopay},
  690.     {'P', doputon},
  691.     {M('p'), dopray},
  692.     {'q', dodrink},
  693.     {'Q', done2},
  694.     {'r', doread},
  695.     {'R', doremring},
  696.     {M('r'), dorub},
  697.     {'s', dosearch, "searching"},
  698.     {'S', dosave},
  699.     {M('s'), dosit},
  700.     {'t', dothrow},
  701.     {'T', dotakeoff},
  702.     {M('t'), doturn},
  703. /*    'u', 'U' : go ne */
  704.     {'u', dountrap}, /* if number_pad is on */
  705.     {M('u'), dountrap},
  706.     {'v', doversion},
  707.     {'V', dohistory},
  708.     {M('v'), doextversion},
  709.     {'w', dowield},
  710.     {'W', dowear},
  711.     {M('w'), dowipe},
  712.     {'x', dovspell},            /* Mike Stephenson */
  713. #ifdef EXPLORE_MODE
  714.     {'X', enter_explore_mode},
  715. #endif
  716. /*    'y', 'Y' : go nw */
  717.     {'z', dozap},
  718.     {'Z', docast},
  719.     {'<', doup},
  720.     {'>', dodown},
  721.     {'/', dowhatis},
  722.     {'&', dowhatdoes},
  723.     {'?', dohelp},
  724.     {M('?'), doextlist},
  725. #ifdef SHELL
  726.     {'!', dosh},
  727. #endif
  728.     {'.', donull, "waiting"},
  729.     {' ', donull, "waiting"},
  730.     {',', dopickup},
  731.     {':', dolook},
  732.     {';', doquickwhatis},
  733.     {'^', doidtrap},
  734.     {'\\', dodiscovered},        /* Robert Viduya */
  735.     {'@', dotogglepickup},
  736.     {WEAPON_SYM,  doprwep},
  737.     {ARMOR_SYM,  doprarm},
  738.     {RING_SYM,  doprring},
  739.     {AMULET_SYM, dopramulet},
  740.     {TOOL_SYM, doprtool},
  741.     {GOLD_SYM, doprgold},
  742.     {SPBOOK_SYM, dovspell},            /* Mike Stephenson */
  743.     {'#', doextcmd},
  744.     {0,0,0}
  745. };
  746.  
  747. const struct ext_func_tab extcmdlist[] = {
  748.     {"adjust", "adjust inventory letters", doorganize},
  749.     {"chat", "talk to someone", dotalk},    /* converse? */
  750.     {"dip", "dip an object into something", dodip},
  751.     {"force", "force a lock", doforce},
  752.     {"invoke", "invoke an object's powers", doinvoke},
  753.     {"jump", "jump to a location", dojump},
  754.     {"loot", "loot a box on the floor", doloot},
  755. #ifdef POLYSELF
  756.     {"monster", "use a monster's special ability", domonability},
  757. #endif
  758.     {"name", "name an item or type of object", ddocall},
  759.     {"offer", "offer a sacrifice to the gods", dosacrifice},
  760.     {"pray", "pray to the gods for help", dopray},
  761.     {"rub", "rub a lamp", dorub},
  762.     {"sit", "sit down", dosit},
  763.     {"turn", "turn undead", doturn},
  764.     {"untrap", "untrap something", dountrap},
  765.     {"version", "list compile time options for this version of NetHack",
  766.         doextversion},
  767.     {"wipe", "wipe off your face", dowipe},
  768.     {"?", "get this list of extended commands", doextlist},
  769.     {NULL, NULL, donull}
  770. };
  771.  
  772. #define unctrl(c)    ((c) <= C('z') ? (0x60 | (c)) : (c))
  773. #define unmeta(c)    (0x7f & (c))
  774.  
  775.  
  776. void
  777. rhack(cmd)
  778. register char *cmd;
  779. {
  780.     register const struct func_tab *tlist = cmdlist;
  781.     boolean firsttime = FALSE;
  782.     register int res;
  783.  
  784.     if(!cmd) {
  785.         firsttime = TRUE;
  786.         flags.nopick = 0;
  787.         cmd = parse();
  788.     }
  789.     if(*cmd == (char)033) {
  790.         flags.move = 0;
  791.         return;
  792.     }
  793. #ifdef REDO
  794.     if (*cmd == DOAGAIN && !in_doagain && saveq[0]) {
  795.         in_doagain = TRUE;
  796.         stail = 0;
  797.         rhack(NULL);    /* read and execute command */
  798.         in_doagain = FALSE;
  799.         return;
  800.     }
  801.     /* Special case of *cmd == ' ' handled better below */
  802.     if(!*cmd || *cmd == (char)0377) {
  803. #else
  804.     if(!*cmd || *cmd == (char)0377 ||
  805.        (!flags.rest_on_space && *cmd == ' ')) {
  806. #endif
  807.         nhbell();
  808.         flags.move = 0;
  809.         return;        /* probably we just had an interrupt */
  810.     }
  811.     if(movecmd(*cmd)) {
  812.     walk:
  813.         if(multi) flags.mv = 1;
  814.         domove();
  815.         return;
  816.     }
  817.     if(movecmd(flags.num_pad ? unmeta(*cmd) : lowc(*cmd))) {
  818.         flags.run = 1;
  819.     rush:
  820.         if(firsttime){
  821.             if(!multi) multi = COLNO;
  822.             u.last_str_turn = 0;
  823.         }
  824.         flags.mv = 1;
  825.         domove();
  826.         return;
  827.     }
  828.     if(*cmd == 'g' && movecmd(cmd[1])) {
  829.         flags.run = 2;
  830.         goto rush;
  831.     }
  832.     if (((*cmd == 'G' || (flags.num_pad && *cmd == '5')) &&
  833.         movecmd(lowc(cmd[1]))) || movecmd(unctrl(*cmd))) {
  834.         flags.run = 3;
  835.         goto rush;
  836.     }
  837.     if((*cmd == 'm' || (flags.num_pad && *cmd == '-')) &&
  838.         movecmd(cmd[1])) {
  839.         flags.run = 0;
  840.         flags.nopick = 1;
  841.         goto walk;
  842.     }
  843.     if(*cmd == 'M' && movecmd(lowc(cmd[1]))) {
  844.         flags.run = 1;
  845.         flags.nopick = 1;
  846.         goto rush;
  847.     }
  848.     if (flags.num_pad && *cmd == '0') {
  849.         (void)ddoinv();    /* A convenience borrowed from the PC */
  850.         flags.move = 0;
  851.         multi = 0;
  852.         return;
  853.     }
  854.     while(tlist->f_char) {
  855.         if((*cmd & 0xff) == (tlist->f_char & 0xff)){
  856.             /* Special case of *cmd == ' ' handled here */
  857.             if (*cmd == ' ' && !flags.rest_on_space)
  858.                 break;
  859.  
  860.             /* Now control-A can stop lengthy commands */
  861.             /* in the PC version only -- use ^C-N otherwise */
  862.             if (tlist->f_text && !occupation && multi)
  863. #ifdef GCC_WARN
  864.                 set_occupation(tlist->f_funct,
  865.                         tlist->f_text, multi);
  866. #else
  867.                 set_occupation(((struct func_tab *)tlist)->f_funct,
  868.                     tlist->f_text, multi);
  869. #endif
  870.             res = (*(tlist->f_funct))();
  871.             if(!res) {
  872.                 flags.move = 0;
  873.                 multi = 0;
  874.             }
  875.             return;
  876.         }
  877.         tlist++;
  878.     }
  879.     { char expcmd[10];
  880.       register char *cp = expcmd;
  881.       while(*cmd && cp-expcmd < sizeof(expcmd)-2) {
  882.         if(*cmd >= 040 && *cmd < 0177)
  883.             *cp++ = *cmd++;
  884.         else if (*cmd & 0200) {
  885.             *cp++ = 'M';
  886.             *cp++ = '-';
  887.             *cp++ = *cmd++ &=~ 0200;
  888.         }
  889.         else {
  890.             *cp++ = '^';
  891.             *cp++ = *cmd++ ^ 0100;
  892.         }
  893.       }
  894.       *cp = 0;
  895.       Norep("Unknown command '%s'.", expcmd);
  896.     }
  897.     multi = flags.move = 0;
  898.     return;
  899. }
  900.  
  901. int
  902. xytod(x, y)    /* convert an x,y pair into a direction code */
  903. schar x, y;
  904. {
  905.     register int dd;
  906.  
  907.     for(dd = 0; dd < 8; dd++)
  908.         if(x == xdir[dd] && y == ydir[dd]) return dd;
  909.  
  910.     return -1;
  911. }
  912.  
  913. #ifdef WALKIES
  914. void
  915. dtoxy(cc,dd)    /* convert a direction code into an x,y pair */
  916. coord *cc;
  917. register int dd;
  918. {
  919.     cc->x = xdir[dd];
  920.     cc->y = ydir[dd];
  921.     return;
  922. }
  923. #endif /* WALKIES */
  924.  
  925. int
  926. movecmd(sym)    /* also sets u.dz, but returns false for <> */
  927. char sym;
  928. {
  929.     register const char *dp;
  930.     register const char *sdp = flags.num_pad ? ndir : sdir;
  931.  
  932.     u.dz = 0;
  933.     if(!(dp = index(sdp, sym))) return 0;
  934.     u.dx = xdir[dp-sdp];
  935.     u.dy = ydir[dp-sdp];
  936.     u.dz = zdir[dp-sdp];
  937. #ifdef POLYSELF
  938.     if (u.dx && u.dy && u.umonnum == PM_GRID_BUG) {
  939.         u.dx = u.dy = 0;
  940.         return 0;
  941.     }
  942. #endif
  943.     return !u.dz;
  944. }
  945.  
  946. int
  947. getdir(s)
  948. const char *s;
  949. {
  950.     char dirsym;
  951.  
  952. #ifdef REDO    
  953.     if(in_doagain)
  954.         dirsym = readchar();
  955.     else
  956. #endif
  957.         dirsym = yn_function (s ? s : "In what direction?", NULL, '\0');
  958. #ifdef REDO
  959.     savech(dirsym);
  960. #endif
  961.     if(dirsym == '.' || dirsym == 's')
  962.         u.dx = u.dy = u.dz = 0;
  963.     else if(!movecmd(dirsym) && !u.dz) {
  964.         if(!index(quitchars, dirsym))
  965.             pline("What a strange direction!");
  966.         return 0;
  967.     }
  968.     if(!u.dz && (Stunned || (Confusion && !rn2(5)))) confdir();
  969.     return 1;
  970. }
  971.  
  972. #endif /* OVL1 */
  973. #ifdef OVLB
  974.  
  975. void
  976. confdir()
  977. {
  978.     register int x =
  979. #ifdef POLYSELF
  980.         (u.umonnum == PM_GRID_BUG) ? 2*rn2(4) :
  981. #endif
  982.                             rn2(8);
  983.     u.dx = xdir[x];
  984.     u.dy = ydir[x];
  985.     return;
  986. }
  987.  
  988. #endif /* OVLB */
  989. #ifdef OVL0
  990.  
  991. int
  992. isok(x,y)
  993. register int x, y;
  994. {
  995.     /* x corresponds to curx, so x==1 is the first column. Ach. %% */
  996.     return x >= 1 && x <= COLNO-1 && y >= 0 && y <= ROWNO-1;
  997. }
  998.  
  999. static NEARDATA int last_multi;
  1000.  
  1001. /*
  1002.  * convert a MAP window position into a movecmd
  1003.  */
  1004. int
  1005. click_to_cmd(x, y, mod)
  1006.     int x, y, mod;
  1007. {
  1008.     x -= u.ux;
  1009.     y -= u.uy;
  1010.     /* convert without using floating point, allowing sloppy clicking */
  1011.     if(x > 2*abs(y))
  1012.     x = 1, y = 0;
  1013.     else if(y > 2*abs(x))
  1014.     x = 0, y = 1;
  1015.     else if(x < -2*abs(y))
  1016.     x = -1, y = 0;
  1017.     else if(y < -2*abs(x))
  1018.     x = 0, y = -1;
  1019.     else
  1020.     x = sgn(x), y = sgn(y);
  1021.  
  1022.     if(x == 0 && y == 0)    /* map click on player to "rest" command */
  1023.     return '.';
  1024.  
  1025.     x = xytod(x, y);
  1026.     if(mod == CLICK_1) {
  1027.     return (flags.num_pad ? ndir[x] : sdir[x]);
  1028.     } else {
  1029.     return (flags.num_pad ? M(ndir[x]) :
  1030.         (sdir[x] - 'a' + 'A')); /* run command */
  1031.     }
  1032. }
  1033.  
  1034. STATIC_OVL char *
  1035. parse()
  1036. {
  1037. #ifdef LINT    /* static char in_line[COLNO]; */
  1038.     char in_line[COLNO];
  1039. #else
  1040.     static char in_line[COLNO];
  1041. #endif
  1042.     register int foo;
  1043.     boolean prezero = FALSE;
  1044.  
  1045.     multi = 0;
  1046.     flags.move = 1;
  1047.     flush_screen(1); /* Flush screen buffer. Put the cursor on the hero. */
  1048.  
  1049.     if (!flags.num_pad || (foo = readchar()) == 'n')
  1050.         for (;;) {
  1051.         foo = readchar();
  1052.         if (foo >= '0' && foo <= '9') {
  1053.             multi = 10 * multi + foo - '0';
  1054.             if (multi < 0 || multi > LARGEST_INT) multi = LARGEST_INT;
  1055.             if (multi > 9) {
  1056.             clear_nhwindow(WIN_MESSAGE);
  1057.             Sprintf(in_line, "Count: %d", multi);
  1058.             pline(in_line);
  1059.             mark_synch();
  1060.             }
  1061.             last_multi = multi;
  1062.             if (!multi && foo == '0') prezero = TRUE;
  1063.         } else break;    /* not a digit */
  1064.         }
  1065.  
  1066.     if (foo == '\033') {   /* esc cancels count (TH) */
  1067.         clear_nhwindow(WIN_MESSAGE);
  1068.         multi = last_multi = 0;
  1069. # ifdef REDO
  1070.     } else if (foo == DOAGAIN || in_doagain) {
  1071.         multi = last_multi;
  1072.     } else {
  1073.         last_multi = multi;
  1074.         savech(0);    /* reset input queue */
  1075.         savech((char)foo);
  1076. # endif
  1077.     }
  1078.  
  1079.     if (multi) {
  1080.         multi--;
  1081.         save_cm = in_line;
  1082.     } else {
  1083.         save_cm = NULL;
  1084.     }
  1085.     in_line[0] = foo;
  1086.     in_line[1] = '\0';
  1087.     if (foo == 'g' || foo == 'G' || (flags.num_pad && foo == '5') ||
  1088.         foo == 'm' || foo == 'M') {
  1089.         foo = readchar();
  1090. #ifdef REDO
  1091.         savech((char)foo);
  1092. #endif
  1093.         in_line[1] = foo;
  1094.         in_line[2] = 0;
  1095.     }
  1096.     clear_nhwindow(WIN_MESSAGE);
  1097.     if (prezero) in_line[0] = '\033';
  1098.     return(in_line);
  1099. }
  1100.  
  1101. #endif /* OVL0 */
  1102. #ifdef OVLB
  1103.  
  1104. #ifdef UNIX
  1105. static
  1106. void
  1107. end_of_input()
  1108. {
  1109.     exit_nhwindows("End of input?");
  1110. #ifndef NOSAVEONHANGUP
  1111.     if(!hu) {
  1112.         hu = TRUE;
  1113.         (void) dosave0();
  1114.     }
  1115. #endif
  1116.     clearlocks();
  1117.     terminate(0);
  1118. }
  1119. #endif
  1120.  
  1121. #endif /* OVLB */
  1122. #ifdef OVL0
  1123.  
  1124. char
  1125. readchar()
  1126. {
  1127.     register int sym;
  1128.     int x, y, mod;
  1129.  
  1130. #ifdef REDO
  1131.     sym = in_doagain ? Getchar() : nh_poskey(&x, &y, &mod);
  1132. #else
  1133.     sym = Getchar();
  1134. #endif
  1135.  
  1136. #ifdef UNIX
  1137. # ifdef NR_OF_EOFS
  1138.     if (sym == EOF) {
  1139.         register int cnt = NR_OF_EOFS;
  1140.       /*
  1141.        * Some SYSV systems seem to return EOFs for various reasons
  1142.        * (?like when one hits break or for interrupted systemcalls?),
  1143.        * and we must see several before we quit.
  1144.        */
  1145.         do {
  1146.         clearerr(stdin);    /* omit if clearerr is undefined */
  1147.         sym = Getchar();
  1148.         } while (--cnt && sym == EOF);
  1149.     }
  1150. # endif /* NR_OF_EOFS */
  1151.     if (sym == EOF)
  1152.         end_of_input();
  1153. #endif /* UNIX */
  1154.  
  1155.     if(sym == 0) /* click event */
  1156.         sym = click_to_cmd(x, y, mod);
  1157.     return((char) sym);
  1158. }
  1159. #endif /* OVL0 */
  1160.  
  1161. /*cmd.c*/
  1162.